package com.wxq.workpad.network.interceptor;

import android.content.Context;
import android.content.pm.ApplicationInfo;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sum.network.error.ERROR;
import com.sum.network.error.NoNetWorkException;
import com.wxq.workpad.accoutInfo.UserInfoManager;
import com.wxq.workpad.utils.log.LogUtils;

import org.jetbrains.annotations.NotNull;


import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;
import java.util.UUID;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;

public class QfInterceptor implements Interceptor {

    public static String HTTP_LOG = "http_log";
    private final Charset UTF8 = Charset.forName("UTF-8");

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        String jsonObject = getPostRequestBodyString(request);
        Request.Builder builder = request.newBuilder();
        String url = request.url().toString();
        String width = request.header("screen-width");
        Headers headers = buildHeaders(url, width, jsonObject);
        for (int i = 0; i < headers.size(); i++) {
            if (request.headers().values(headers.name(i)).size() == 0) {
                builder.addHeader(headers.name(i), headers.value(i));
            }
        }

        //支持在header中自定义请求的method
        String customMethod = request.header("method");
        if (customMethod != null) {
            RequestBody body = request.body();
            if (body == null) {
                if ("POST".equals(customMethod) ||
                        "PUT".equals(customMethod) ||
                        "PATCH".equals(customMethod) ||
                        "PROPPATCH".equals(customMethod) ||
                        "REPORT".equals(customMethod)) {
                    body = RequestBody.create((MediaType.parse("application/json; charset=utf-8")),"{}");
                }
            } else {
                if ("GET".equals(customMethod) ||
                        "HEAD".equals(customMethod)) {
                    body = null;
                }
            }
            builder.method(customMethod, body);
        }
        // 设置添加头的request
        request = builder.build();
        // saveRequestParmerLog
        Response response;
        if (url.endsWith(".apk") || url.endsWith(".zip")) {
            response = chain.proceed(request);
        } else {
            response = handleResponse(chain, request);
        }

        return response;
    }

    public static Headers buildHeaders(String jsonObject) {
        return buildHeaders("", "", jsonObject);
    }

    public static Headers buildHeaders(String url, String width, String jsonObject) {
        Headers.Builder headersBuilder = new Headers.Builder();
//        String userAgent = "" + AppConfig.USERAGENT.replaceAll(" ", "");
        String nonce = UUID.randomUUID().toString().replaceAll("-", "");
        long timestamp = System.currentTimeMillis();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        String date = sdf.format(new Date());
//        String authorization = "" + UserDataUtils.getInstance().getHeader_bearerToken();
        headersBuilder.add("Content-Type", "application/json")
                .add("ticket", UserInfoManager.INSTANCE.getTicket())
                .add("sign",   UserInfoManager.INSTANCE.getSign())
                .add("ts",   UserInfoManager.INSTANCE.getTs())
                .add("inner-version", "")
                .add("device", "")
                .add("device-type", "1");




        return headersBuilder.build();
    }

    @NotNull
    private Response handleResponse(Chain chain, Request request) throws IOException {
        //添加日志
        RequestBody requestBody = request.body();
        String body = null;
        if (requestBody != null) {
            Buffer buffer = new Buffer();
            requestBody.writeTo(buffer);
            Charset charset = UTF8;
            MediaType contentType = requestBody.contentType();
            if (contentType != null) {
                charset = contentType.charset(UTF8);
            }
            String bodys = buffer.readString(charset);
            try {
                body = URLDecoder.decode(bodys);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        long startNs = System.nanoTime();
        Response response = null;
        try {
            response = chain.proceed(request);
        } catch (Exception e) {
            String url = request.url().toString();
            LogUtils.e(HTTP_LOG, "url-->" + url + "\n" + e.toString());
            //这里主要处理的是网络问题。  显示弹框等问题
//            throw new  NoNetWorkException(ERROR.UNKNOWN,e);
//            RetrofitTemp.INSTANCE.handleFailure("cause==>" + e.getCause() + "\nmessage==>" + e.getMessage(), url);
            throw e;
        }
        if (response != null) {
            try {
                ResponseBody responseBody = response.body();
                String rBody;
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE);
                Buffer buffer = source.buffer();
                Charset charset = UTF8;
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    try {
                        charset = contentType.charset(UTF8);
                    } catch (UnsupportedCharsetException e) {
                        e.printStackTrace();
                    }
                }
                rBody = buffer.clone().readString(charset);
                String reqBody = LogJsonUtil.formatJson(body);
                String url = request.url().toString();

                printLog(request, rBody, response, reqBody, body);


//                if (response.code() == 200||response.code() == 201) {
//                    if (rBody.startsWith("[")) {
//                        JSONArray baseJsonObject = JSON.parseArray(rBody);
//                        // 说明是成功的
//                        JSONObject successObj=new JSONObject();
//                        successObj.put("errorCode", 0);
//                        successObj.put("errorMsg", "");
//                        successObj.put("data",baseJsonObject);
//                        ResponseBody newBody = ResponseBody.create(successObj.toJSONString(), response.body().contentType());
//                        return response.newBuilder().body(newBody).build();
//                    }else {
//
//                        JSONObject baseJsonObject = JSON.parseObject(rBody);
//                        if (baseJsonObject.getInteger("code")==null) {
//                            // 说明是成功的
//                            JSONObject successObj=new JSONObject();
//                            successObj.put("errorCode", 0);
//                            successObj.put("errorMsg", "");
//                            successObj.put("data",baseJsonObject);
//                            ResponseBody newBody = ResponseBody.create(successObj.toJSONString(), response.body().contentType());
//                            return response.newBuilder().body(newBody).build();
//                        }else {
//                            // 说明有问题
//                            int ret = baseJsonObject.getInteger("code");
//                            String text = baseJsonObject.getString("text");
//                            // 额外处理下错误 但是不抛异常
//                            handleRetError(ret, text, url);
//                            JSONObject successObj=new JSONObject();
//                            successObj.put("errorCode", ret);
//                            successObj.put("errorMsg", text);
//                            successObj.put("data",baseJsonObject);
//                            ResponseBody newBody = ResponseBody.create(successObj.toJSONString(), response.body().contentType());
//                            return response.newBuilder().body(newBody).build();
//                        }
//                    }
//
//                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return response;
    }

    /**
     * 针对非0的ret进行统一的处理
     *
     * @param ret
     * @param text
     * @param url
     */
    private void handleRetError(int ret, String text, String url) {
        HandlerUtils.getInstance().post(new Runnable() {
            @Override
            public void run() {
//                NetErrorHandler.handleRet(ret, text, url);
            }
        });
    }

    /**
     * 处理ret为-200时，加密的情况
     *
     * @param response
     * @return
     */
//    private Response handleEncrypt(Response response, JSONObject baseJsonObject) {
//        String firstReverseMi = new StringBuffer(baseJsonObject.getString("mi")).reverse().toString();
//        String firstDecode = new String(Base64Utils.decode(firstReverseMi));
//        String secondReverseMi = new StringBuffer(firstDecode).reverse().toString();
//        String secondDecode = new String(Base64Utils.decode(secondReverseMi));
//
//        baseJsonObject.put("ret", 0);
//        baseJsonObject.put("data", JSON.parse(secondDecode));
//        ResponseBody newBody = ResponseBody.create(baseJsonObject.toJSONString(), response.body().contentType());
//        return response.newBuilder().body(newBody).build();
//    }

    private void printLog(Request request, String rBody, Response response, String reqBody, String body) {
        String url = request.url().toString();
        String reqlog = "发送请求: method：" + request.method()
                + "\nurl：" + url
                + "\n请求头：" + request.headers()
                + "\n请求参数: " + reqBody;

        String responseHeads = "";

        if (response.headers() != null) {
            responseHeads = response.headers() + "";
        }
        try {
            int code = response.code();
            String resultlog = "收到响应: code:" + code
                    + "\n请求url：" + response.request().url()
                    + "\n返回头信息：\n" + responseHeads
                    + "\n返回json数据：\n" + LogJsonUtil.formatJson(rBody);
           printResponseLog("retrofit======log" + reqlog + "\n\n-----------response-----------\n" + resultlog);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String getPostRequestBodyString(Request request) {
        String jsonObject = "";
        RequestBody requestBody = request.body();
        if (requestBody == null) {
            return jsonObject;
        } else {
//            if (requestBody instanceof FormBody) {
//                //传统表单方式请求
//                //暂时不处理，用不到
//            } else
            if (requestBody instanceof MultipartBody) {
                //文件方式请求
                //暂时不处理，用不到
            } else {
                try {
                    if (requestBody.contentLength() == 0) {
                        jsonObject = "";
                    } else {
                        jsonObject = getParamContent(requestBody);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
        return jsonObject;
    }

    /**
     * 获取常规post请求参数
     */
    private String getParamContent(RequestBody body) throws IOException {
        Buffer buffer = new Buffer();
        body.writeTo(buffer);
        return buffer.readUtf8();
    }


    /**
     * 打印日志到控制台（解决Android控制台丢失长日志记录）
     *
     * @param content
     */
    public void printResponseLog(String content) {
        // 1. 测试控制台最多打印4062个字节，不同情况稍有出入（注意：这里是字节，不是字符！！）
        // 2. 字符串默认字符集编码是utf-8，它是变长编码一个字符用1~4个字节表示
        // 3. 这里字符长度小于1000，即字节长度小于4000，则直接打印，避免执行后续流程，提高性能哈
        if (content.length() < 1000) {
            LogUtils.e(HTTP_LOG, content);
            return;
        }

        // 一次打印的最大字节数
        int maxByteNum = 4000;

        // 字符串转字节数组
        byte[] bytes = content.getBytes();

        // 超出范围直接打印
        if (maxByteNum >= bytes.length) {
            LogUtils.e(HTTP_LOG, content);
            return;
        }

        // 分段打印计数
        int count = 1;

        // 在数组范围内，则循环分段
        while (maxByteNum < bytes.length) {
            // 按字节长度截取字符串
            String subStr = cutStr(bytes, maxByteNum);

            // 打印日志
            String desc = String.format("分段打印(%s):%s", count++, subStr);

            LogUtils.e(HTTP_LOG, desc);
            // 截取出尚未打印字节数组
            bytes = Arrays.copyOfRange(bytes, subStr.getBytes().length, bytes.length);

            // 可根据需求添加一个次数限制，避免有超长日志一直打印
            /*if (count == 10) {
                break;
            }*/
        }
        LogUtils.e(HTTP_LOG, String.format("分段打印(%s):%s", count, new String(bytes)));
        // 打印剩余部分
//        Log.println(priority, tag, String.format("分段打印(%s):%s", count, new String(bytes)));
    }


    /**
     * 按字节长度截取字节数组为字符串
     *
     * @param bytes
     * @param subLength
     * @return
     */
    public String cutStr(byte[] bytes, int subLength) {
        // 边界判断
        if (bytes == null || subLength < 1) {
            return null;
        }

        // 超出范围直接返回
        if (subLength >= bytes.length) {
            return new String(bytes);
        }

        // 复制出定长字节数组，转为字符串
        String subStr = new String(Arrays.copyOf(bytes, subLength));

        // 避免末尾字符是被拆分的，这里减1使字符串保持完整
        return subStr.substring(0, subStr.length() - 1);
    }

    public boolean isDebug(Context context) {
        boolean isDebug = context.getApplicationInfo() != null &&
                (context.getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        return isDebug;
    }

}
